import { createLogger } from '../utils/logging'
import { MusicInstanceInterface, SoundInstanceInterface, SoundInterface, MUSIC, SOUNDS } from './interface'

const { Howl, Howler } = require('howler')

const logger = createLogger('sound/howler')

export class WrappedSoundInstance extends SoundInstanceInterface{
  constructor(key, url){
    super(key, url);
    this.howl = null;
  }

  load(){
    return Promise.race([
      new Promise((resolve, reject) => {
        setTimeout(reject, G_IS_DEV ? 500 : 5000);
      }),
      new Promise((resolve, reject) => {
        this.howl = new Howl({
          src: 'res/sounds/' + this.url + '.mp3',
          autoplay: false,
          loop: false,
          volume: 0,
          preload: true,
          pool: 20,
          onload: () => {
            resolve();
          },
          onloaderror: (id, err) => {
            logger.warn(this, 'Sound', this.url, '加载错误:', id, err);
            this.howl = null;
            resolve();
          },
          onplayerror: (id, err) => {
            logger.warn(this, 'Sound', this.url, '播放失败:', id, err);
          }
        })
      })
    ])
  }

  play(volume){
    if(this.howl){
      const instance = this.howl.play();
      this.howl.volume(volume, instance);
    }
  }

  deinitialize(){
    if(this.howl){
      this.howl.unload();
      this.howl = null;
    }
  }
}

export class WrappedMusicInstance extends MusicInstanceInterface{
  constructor(key, url){
    super(key, url);
    this.howl = null;
    this.instance = null;
    this.playing = false;
  }

  load(){
    return Promise.race([
      new Promise((resolve, reject) => {
        setTimeout(reject, G_IS_DEV ? 500 : 5000);
      }),
      new Promise((resolve, reject) => {
        this.howl = new Howl({
          src: 'res/sounds/music/' + this.url + '.mp3',
          autoplay: false,
          loop: true,
          html5: true,
          volume: 1,
          preload: true,
          pool: 2,
          onunlock: () => {
            if(this.playing){
              logger.log('Playing music after manual unlock')
              this.play();
            }
          },
          onload: () => {
            resolve();
          },
          onloaderror: (id, err) => {
            logger.warn(this, 'Music', this.url, '加载错误:', id, err);
            this.howl = null;
            resolve();
          },
          onplayerror: (id, err) => {
            logger.warn(this, 'Music', this.url, '播放失败:', id, err);
          }
        })
      })
    ])
  }

  stop(){
    if(this.howl && this.instance){
      this.playing = false;
      this.howl.pause(this.instance);
    }
  }

  play(volume){
    if(this.howl){
      this.playing = true;
      this.howl.volume(volume);
      if(this.instance){
        this.howl.play(this.instance);
      } else {
        this.instance = this.howl.play();
      }
    }
  }

  isPlaying(){
    return this.playing;
  }

  setVolume(volume){
    if(this.howl){
      this.howl.volume(volume);
    }
  }

  deinitialize(){
    if(this.howl){
      this.howl.unload();
      this.howl = null;
      this.instance = null;
    }
  }
}

export class SoundImplHowler extends SoundInterface{
  constructor(app){
    Howler.mobileAutoEnable = true;
    Howler.autoUnlock = true;
    Howler.autoSuspend = false;
    Howler.html5PoolSize = 20;
    Howler.pos(0, 0, 0);

    super(app, WrappedSoundInstance, WrappedMusicInstance);
  }

  deinitialize(){
    return super.deinitialize().then(() => Howler.unload());
  }
}